<template>
  <div class="form-render">
    <!-- geomap的form配置比较特殊，依据glyph来进行，单独写个组件   -->
    <geomap-form
      v-if="isGeo"
      :form-data="formData"
      @change="onPropertyChange"
    />
    <vistabs-form
      v-else-if="isVistabs"
      :form-data="formData"
      @change="onPropertyChange"
    />
    <configuration-form
      v-else-if="isConfiguration"
      :form-data="formData"
      @change="onPropertyChange"
    />
    <template v-else-if="isFilterForm">
      <filter-setting-form
        form-title="数据"
        form-name="data"
        :form-data="formData"
        :panel-list="
          propertyPanelList.filter((item) => item.group === 'filterData')
        "
        @change="onPropertyChange"
      />
      <filter-setting-form
        form-title="样式"
        form-name="style"
        :form-data="formData"
        :panel-list="
          propertyPanelList.filter((item) => item.group === 'property')
        "
        :show-form-title-line="true"
        @change="onPropertyChange"
      />
    </template>
    <graph-form
      v-else-if="isGraph"
      :chart-type="chartType"
      :dataset-list="datasetList"
      :form-data="formData"
      :project-id="projectId"
      :panel-list="propertyPanelList"
      :disabled="!isProjectOwner"
      @propertyChange="onPropertyChange"
      @change="onGraphConfigChange"
      @relateWidgetsChange="(value) => $emit('change', value)"
    />
    <template v-else>
      <!-- 选择chartType额外处理 -->
      <fetch-form
        :form-data="fetchFormData"
        :panel-list="fetchPanelList"
        :chart-type="chartType"
        :table-columns="tableColumns"
        :widget-type="widgetType"
        :dataset-list="datasetList"
        :project-id="projectId"
        @change="onFetchConfigChange"
      >
        <template #chartTypeSlot>
          <a-form
            :label-col="{ span: labelCol }"
            :wrapper-col="{ span: wrapperCol }"
            :class="{ 'current-chart-type-div': chartTypeChangeFlag }"
          >
            <div class="panel">
              <a-form-item label="可视化类型">
                <a-radio-group
                  v-if="chartTypeChangeFlag"
                  :value="selectedChartType"
                  class="current-chart-type-radio-group"
                  size="small"
                >
                  <a-list
                    :grid="{ column: 4, gutter: 4 }"
                    :data-source="visTypeList"
                  >
                    <a-list-item slot="renderItem" slot-scope="t">
                      <a-radio-button
                        :value="t.name"
                        @click="() => onChartTypeChange(t.name)"
                      >
                        <a-tooltip>
                          <template slot="title">{{ t.title }}</template>
                          <a-icon-font :type="t.iconSrc" />
                        </a-tooltip>
                      </a-radio-button>
                    </a-list-item>
                  </a-list>
                </a-radio-group>
                <template v-else>{{ chartType }}</template>
              </a-form-item>
            </div>
          </a-form>
          <!--
          <a-form
            v-else
            :label-col="{ span: labelCol }"
            :wrapper-col="{ span: wrapperCol }"
          >
            <div class="panel">
              <a-form-item label="可视化类型">
                {{chartType}}
              </a-form-item>
            </div>
          </a-form>
          -->
        </template>
      </fetch-form>
      <!-- 知识图谱-实体面板中编辑chart配置特有选项 -->
      <div v-if="interactActive" class="interact-setting">
        <!-- <div class="split-line"></div> -->
        <div class="interact-content">
          <div class="panel-title-hr"></div>
          <span class="setting-text">交互</span>
          <a-switch v-model="interactOn" @change="onInteractChange" />
        </div>
      </div>
      <property-form
        v-if="chartType !== 'table'"
        :form-data="formData"
        :panel-list="propertyPanelList"
        :chart-type="chartType"
        @change="onPropertyChange"
      />
      <!-- 目前联动需要满足同一pipeline 处理链下的关系 -->
      <interact-form
        v-if="
          !['table', 'bubbleScatterChart'].includes(chartType) &&
          relateWidgets.length > 0
        "
        :checked-widgets="checkedWidgets"
        :relate-widgets="relateWidgets"
        :filter-name="formData.labelKey"
        :current-name="formData.title ? formData.title : currentWidgetId"
        @change="
          (checkedList) => {
            checkboxSelect(checkedList)
          }
        "
      />
      <!-- 经济项目某些特例需要去除同一pipeline下关系的约束，放开全部列表，后续这种情况多了需考虑做成通用组件 -->
      <bubble-interact-form
        v-if="chartType === 'bubbleScatterChart'"
        :interact-column-name="interactColumnName"
        @relateWidgetsChange="(value) => $emit('change', value)"
        @interactColumnChange="onInteractColumnChange"
      />
    </template>
  </div>
</template>

<script lang="ts">
import { Vue, Prop, Component, Watch } from 'vue-property-decorator'
import PropertyForm from '@/components/common/VisualizationDashboard/PropertyForm.vue'
import FetchForm from '@/components/common/VisualizationDashboard/FetchForm.vue'
// import InteractForm from '@/components/common/VisualizationDashboard/InteractForm.vue'
// import GeomapForm from '@/components/common/VisualizationDashboard/GeomapForm.vue'
import ConfigurationForm from '@/components/common/VisualizationDashboard/ConfigurationForm.vue'
import FilterSettingForm from '@/components/common/VisualizationDashboard/FilterSettingForm.vue'
// import GraphForm from '@/components/common/VisualizationDashboard/GraphForm.vue'
// import VistabsForm from '@/components/common/VisualizationDashboard/VistabsForm.vue'
// import BubbleInteractForm from '@/components/common/VisualizationDashboard/BubbleInteractForm.vue'
import {
  chartList,
  GRAPH_ARRAY,
  chartTypes,
  isAggrStatus,
} from '@/config/contant'
import {
  checkFieldsValue,
  IKeyValue,
  queryWidgetData,
  parseGetDataResult,
  queryGraphWidgetData,
  combineGraphLineChartData,
} from '@/components/common/VisualizationDashboard/util'
import {
  IDatasetList,
  IWidgetInfo,
  IWidgetJson,
  IColumn,
  IPanel,
} from '@/components/common/VisualizationDashboard/interface'
/* eslint-disable unicorn/prevent-abbreviations */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { isEqual, cloneDeep } from 'lodash'
import { publicPath } from '@/api/constants'
import VisualizationStore from '@/store/modules/visualization'
import { getRelateWidgets } from '@/api/widget'
import UserStore from '@/store/modules/user'

@Component({
  components: {
    PropertyForm,
    FetchForm,
    // GeomapForm,
    ConfigurationForm,
    FilterSettingForm,
    // InteractForm,
    // GraphForm,
    // VistabsForm,
    // BubbleInteractForm,
  },
})
export default class FormRender extends Vue {
  @Prop({ default: () => [] }) panelList!: IPanel[]
  @Prop({
    type: Number,
    required: false,
    default() {
      return 8
    },
  })
  labelCol!: number

  @Prop({
    type: Number,
    required: false,
    default() {
      return 16
    },
  })
  wrapperCol!: number

  @Prop({
    type: Object,
    required: true,
    default(): IKeyValue {
      return {}
    },
  })
  formData!: IKeyValue

  @Prop({
    type: Object,
    required: true,
    default(): IKeyValue {
      return {}
    },
  })
  widgetInfo!: IWidgetInfo

  @Prop({
    type: Array,
    default() {
      return []
    },
  })
  interactInfo?: Array<any> //  item 中存储的关联图表信息,如status 等

  @Prop({
    default() {
      return false
    },
  })
  interactActive?: any //  是否开启交互 【图谱中chart 特有】

  @Prop() chartType!: string
  @Prop() widgetType!: 'system' | 'pipeline' | 'dataset' // system-系统组件 pipeline - pipeline组件
  @Prop({ default: () => [] }) datasetList!: IDatasetList // 数据集列表
  @Prop({ default: '' }) projectId!: '' // 项目id，查询数据集相关列时校验权限用
  @Prop({ default: 'panel' }) from!: String //  FormRender 使用的源头 为render interactForm 做判断

  // 修改chartType额外处理 start #####################################################################
  @Prop({ default: () => false }) chartTypeChangeFlag!: boolean // 是否可以修改chartType
  private publicPath = publicPath // 基础URL
  private currentChartType: string = ''
  private selectedChartType: string = 'barChart' // 选中的chart大类

  /**
   * chart 大类别list
   */
  private get visTypeList() {
    return chartList.filter((item) => item.inModal === true)
  }
  private get chartCategoryList() {
    return Object.keys(chartTypes)
      .filter(
        (key) =>
          ![
            'text',
            'table',
            'configuration',
            'parallelCoordinates',
            'geographicMap',
            'filterForm',
            'graph',
            'vistabs',
          ].includes(key)
      )
      .reduce((pre, key) => {
        pre.push({
          // @ts-ignore
          name: key,
          ...chartTypes[key],
        })
        return pre
      }, [])
  }

  private relateWidgets: any = [] //  关联图表列表
  private checkedWidgets: any = [] //  勾选的选项 如：[12394, 15869]
  private loseWidgets: any = [] //  lose_con [12394, ...]

  public checkboxSelect(checkedList: any[]) {
    const result: any = this.transferRelateWidgetList(checkedList)
    this.onInteractConfigChange(result)
  }

  //  转换form table list info 为 后端接受的数据结构
  public transferRelateWidgetList(list: any[]) {
    const widgetsList = cloneDeep(this.relateWidgets)
    widgetsList.forEach((item: any) => {
      delete item.label
      delete item.value
      if (list.includes(item.widgetId)) {
        item.status = 'connected'
      } else {
        item.status = 'available'
      }

      if (this.loseWidgets.includes(item.widgetId)) {
        item.status = 'lose_connection'
      }
    })
    return widgetsList
  }
  //  InteractConfig变动，发起update
  private onInteractConfigChange(list: Array<any>) {
    this.$emit('change', {
      type: 'interact',
      data: {
        relateWidgets: list,
      },
    })
  }

  private get currentWidgetId() {
    return VisualizationStore.currentGridItem?.widgetId
  }

  private get isProjectOwner() {
    return UserStore.isProjectOwner
  }
  //  交互配置是否开关
  private interactOn: boolean = false

  @Watch('interactActive', { immediate: true, deep: true })
  private onInteractActive(newValue: any) {
    if (newValue) {
      this.interactOn = newValue.turnOn
    }
  }

  @Watch('widgetInfo', { immediate: true, deep: true })
  private onWigetInfoChange(newValue: IKeyValue, oldValue: IKeyValue) {
    if (this.from === 'panel') {
      this.$nextTick(async () => {
        if (
          !newValue?.id ||
          newValue?.id === oldValue?.id ||
          ['table', 'filterForm'].includes(this.chartType) ||
          newValue.type !== 'task'
        ) {
          return
        }

        const { activeSettingItem } = VisualizationStore
        if (this.currentWidgetId && activeSettingItem === 'chart') {
          const parsedData = this.convertWidgetJsonToFormData(
            this.widgetInfo.widgetJson
          )
          const response: any = await this.getRelatedWidgets(
            this.currentWidgetId,
            parsedData.labelKeyObj
          )
          const { data } = response
          if (data.code === 100 && data.result?.relateWidgets) {
            this.relateWidgets =
              this.parseRelateWidgets(data.result?.relateWidgets) ?? []
            this.parseInteractInfo()
          }
        }
      })
    }
  }

  //  获取 勾选的关联图表 列表；
  private parseInteractInfo() {
    if (this.interactInfo && this.interactInfo.length > 0) {
      this.interactInfo.forEach((item: any) => {
        if (item.status === 'connected' || item.status === 'lose_connection') {
          //  lose_connection 意味着之前是connected
          this.checkedWidgets.push(item.widgetId)
        }
      })
    }
  }

  //  解析relatedWidget 为form checkbox 可展示的数据结构
  private parseRelateWidgets(list: Array<any>) {
    const result: any = []
    list.forEach((item: any) => {
      result.push({
        ...item,
        label: item.chartName ? item.chartName : item.widgetId,
        value: item.widgetId,
        disabled: item.status === 'lose_connection',
      })

      if (item.status === 'lose_connection') {
        //  记录lose_connection 的id
        this.loseWidgets.push(item.widgetId)
      }
    })
    return result
  }

  private async getRelatedWidgets(widgetId: number, labelObject: any) {
    const relateWidgets = await getRelateWidgets({
      data: {
        dashboardId: VisualizationStore.currentDashboard.id,
        projectId: Number(this.projectId),
        widgetId,
        xattrStr: labelObject?.value,
      },
    })
    return relateWidgets
  }

  private convertWidgetJsonToFormData(widgetJson?: IWidgetJson) {
    if (!widgetJson || !widgetJson.config) {
      return {
        isAggr: isAggrStatus.DEFAULT,
        topN: this.chartType === 'pieChart' ? 10000 : 1000,
      }
    }
    const {
      isAggr,
      config: { keys, topN, values, groups = [] },
    } = widgetJson
    const data: any = {
      isAggr,
      topN,
      labelKeyObj: {
        value: '',
        sort: '',
        desc: '',
      },
      valueKeyObjList: [
        {
          value: '',
          func: 'sum',
          sort: '',
        },
      ],
    }
    if (keys[0]) {
      data.labelKeyObj = {
        value: keys[0].col,
        sort: keys[0].sort,
        desc: keys[0].desc,
      }
    }
    if (keys[1]) {
      data.yLabelKeyObj = {
        value: keys[1].col,
        sort: keys[1].sort,
      }
    }
    if (values.length > 0) {
      data.valueKeyObjList = values.map((v) => ({
        value: v.col,
        func: v.aggregate_type,
        sort: v.sort,
      }))
    }
    if (groups.length > 0) {
      data.groupBy = groups[0].col
    }

    return data
  }

  @Watch('chartType', { immediate: true })
  onChartTypeProp() {
    this.currentChartType = this.chartType
    if (this.chartType) {
      this.selectedChartType = this.chartType
    }
  }

  private onChartTypeChange(chartType: string) {
    if (this.chartTypeChangeFlag && chartType !== this.currentChartType) {
      this.$emit('chartTypeChange', chartType)
    }
  }
  // 修改chartType额外处理 end #####################################################################

  private tableColumns: IColumn[] = []
  // 获取数据获取相关的panel
  private get fetchPanelList() {
    return this.panelList.filter((list) => list.type === 'fetch')
  }

  private get isVistabs() {
    return this.chartType === 'vistabs'
  }

  private get isGeo() {
    return this.chartType === 'geographicMap'
  }

  private get isGraph() {
    return GRAPH_ARRAY.includes(this.chartType)
  }

  private get isConfiguration() {
    return this.chartType === 'configuration'
  }

  /** 是否是筛选组件 */
  private get isFilterForm() {
    return this.chartType === 'filterForm'
  }
  // 获取属性配置相关的panel
  private get propertyPanelList() {
    return this.panelList.filter((list) => list.type !== 'fetch')
  }

  private get fetchFormData() {
    if (this.chartType === 'table' || this.isGraph) {
      return this.formData
    }
    return this.widgetInfo
  }

  /**
   * 处理widgetJson里面的值
   */
  private parseWidgetJson(widgetJson: IKeyValue) {
    const { config } = widgetJson
    config.topN = Number.parseInt(config.topN, 10)
    return widgetJson
  }

  /**
   * 判断是否能发送请求查询数据
   */
  private checkIfQueryWidgetData(widgetJson: IWidgetJson, chartType?: string) {
    const { keys, values, confidence } = widgetJson.config
    if (
      chartType === 'gaugeChart' &&
      values.length > 0 &&
      values.every((v: { col: string }) => v.col)
    ) {
      return true
    }
    if (
      keys.length > 0 &&
      keys[0].col &&
      values.length > 0 &&
      values.every((v: { col: string }) => v.col) &&
      confidence?.lower !== '' &&
      confidence?.upper !== '' // 检测confidence
    ) {
      return chartType === 'dualAxesChart' ? values.length > 1 : true
    }
    return false
  }

  private isEnableFetch(
    widgetInfo: IWidgetInfo,
    extraFormData: IKeyValue = {}
  ) {
    const { widgetJson, tableJson } = widgetInfo
    if (this.chartType !== 'table' && widgetJson) {
      // chart 情况
      if (!widgetJson.config) {
        this.$emit('reset', {
          type: 'fetch',
          widgetInfo,
          data: [],
        })
        return false
      }
      if (!checkFieldsValue(widgetJson.config)) {
        return false
      }

      if (isEqual(this.widgetInfo.widgetJson, widgetJson)) {
        // widget未改变，不重新获取
        return false
      }

      if (!this.checkIfQueryWidgetData(widgetJson, this.chartType)) {
        // 检查参数合法性
        return false
      }
    } else if (this.chartType === 'table') {
      // table情况，取tableJson 进行获取
      if (!tableJson) {
        // 无需重新获取数据
        this.$emit('change', {
          type: 'fetch',
          widgetInfo,
          extraFormData,
        })
        return false
      }
    }
    return true
  }

  /**
   * 获取数据相关的配置变化（FetchForm）
   * @param extraFormData 需要塞到formData里面的数据
   */
  private async onFetchConfigChange(
    widgetInfo: IWidgetInfo,
    extraFormData: IKeyValue = {}
  ) {
    const { tableJson } = widgetInfo
    const parameters: any = widgetInfo
    if (!this.isEnableFetch(widgetInfo, extraFormData)) {
      return
    }
    // k-graph 传参处理
    if (typeof parameters.id === 'string') {
      parameters.tableName = parameters.id
    }
    if (this.chartType === 'table') {
      parameters.tableJson = tableJson
      delete parameters.widgetJson
    }
    const value: {
      columns: IColumn[]
      data: any[]
      page?: { curPage: number; pageSize: number; totalElements: number }
    } = await queryWidgetData(parameters)
    this.tableColumns = value.columns
    const dataResult = parseGetDataResult(value)
    // console.log('onFetchConfigChange',dataResult)
    // if (this.chartType !== 'table' && widgetInfo.widgetJson !== undefined) {
    //   dataResult = restructGetDataResult(dataResult, widgetInfo.widgetJson)
    // }
    this.$emit('change', {
      type: 'fetch',
      widgetInfo,
      data: dataResult,
      extraFormData: {
        columns: value.columns.map((c) => c.name),
        ...extraFormData,
        ...(value.page || {}),
      },
    })
  }

  /**
   * graph config 更改
   */
  private async onGraphConfigChange(fieldName: string) {
    let emitConfig: any = {}
    const fetchKeys = new Set([
      'dataId',
      'subDataId',
      'labelKeyObj',
      'valueKeyObjList',
      'combineField',
      'topN',
    ])
    if (fetchKeys.has(fieldName)) {
      const graphData = await this.fetchGraphData(fieldName)
      if (graphData) {
        emitConfig = {
          type: 'fetch',
          ...graphData,
        }
      }
    }

    this.$emit('change', emitConfig)
  }

  /**
   * 获取图数据
   */
  private async fetchGraphData(fieldName: string) {
    const {
      dataId,
      subDataId,
      combineField,
      widgetInfo,
      labelKeyObj = {},
      valueKeyObjList = [],
      subChartOptions = {},
    } = this.formData // subDataId, combineField 为 graph-linechart demo 加的
    if (!dataId) {
      return null
    }
    // eslint-disable-next-line prefer-destructuring
    let value: any = this.formData.value
    if (fieldName === 'dataId') {
      value = await queryGraphWidgetData({
        fileName: dataId,
        projectId: this.projectId,
      })
    }

    // ********* graph-line-chart demo start *********
    if (
      subDataId &&
      combineField &&
      widgetInfo &&
      this.checkIfQueryWidgetData(widgetInfo.widgetJson)
    ) {
      // 查询子数据，这里特指 graph-linechart 中的 linechart 数据
      const subValue: {
        columns: IColumn[]
        data: any[]
        page?: { curPage: number; pageSize: number; totalElements: number }
      } = await queryWidgetData(widgetInfo)
      const dataResult = parseGetDataResult(subValue)
      // if (this.chartType !== 'table' && widgetInfo.widgetJson !== undefined) {
      //   dataResult = restructGetDataResult(dataResult, widgetInfo.widgetJson)
      // }
      subChartOptions.value = dataResult
      subChartOptions.labelKey = labelKeyObj.value
      subChartOptions.xAxisAttribute = labelKeyObj.value
      subChartOptions.valueKey = valueKeyObjList[0].value
      subChartOptions.yAxisAttribute = valueKeyObjList.map((l: any) => l.value)
    }
    // ********* graph-line-chart demo end *********

    return {
      data: combineGraphLineChartData(value, subChartOptions, combineField),
    }
  }
  //  交互配置更改
  private onInteractChange(value: boolean) {
    this.$emit('change', {
      type: 'interact',
      data: value,
    })
  }

  private onPropertyChange(config: IKeyValue) {
    this.$emit('change', {
      type: 'property',
      data: config,
    })
  }

  /** ********** for economic bubblechart demo start  ********** */
  private get interactColumnName() {
    return this.formData.interactColumnName || this.formData.labelKey
  }
  private onInteractColumnChange(data: any) {
    this.$emit('change', {
      type: 'property',
      data: {
        ...this.formData,
        ...data,
      },
    })
  }
  /** ********** for economic bubblechart demo end   ********** */
}
</script>

<style lang="less">
.form-render {
  background-color: #f9f9fc;
  height: 100%;
  overflow-y: auto;
  padding: 16px;

  &::-webkit-scrollbar {
    height: 6px;
    visibility: hidden;
    width: 6px;

    &:horizontal {
      display: none;
      height: 0;
      width: 0;
    }
  }

  &::-webkit-scrollbar-thumb {
    background: rgba(144, 147, 153, 0.5);
    border-radius: 6px;
    visibility: hidden;

    &:horizontal {
      display: none;
    }
  }

  &:hover {
    &::-webkit-scrollbar {
      visibility: visible;
    }

    &::-webkit-scrollbar-thumb {
      visibility: visible;
    }
  }

  &::-webkit-scrollbar-track {
    background: transparent;
    border-radius: 5px;
  }

  .current-chart-type-div {
    .ant-kg-appl-form-item-control {
      line-height: 8px;
      padding-top: 8px;
    }

    .ant-kg-appl-list-item {
      margin-bottom: 8px;

      img {
        width: 20px;
      }

      .chart-cat-img {
        margin-bottom: 2px;
        width: 15px;
      }
    }
  }

  .ant-kg-appl-input-number {
    width: 100%;
  }

  .sub-form-item {
    label {
      color: #5d637e;
      font-size: 12px;
      padding-left: 12px;
    }

    .ant-kg-appl-form-item-label,
    .ant-kg-appl-form-item-control {
      line-height: 24px;
    }
  }

  .ant-kg-appl-form-item-label {
    text-align: left;
  }

  .ant-kg-appl-form-item.vertical {
    .ant-kg-appl-col {
      width: 100%;
    }
  }

  .ant-kg-appl-form-item {
    margin-bottom: 0;
  }

  .split-line {
    background-color: #e9e9e9;
    height: 1px;
    left: 0;
    margin-bottom: 10px;
    position: absolute;
    right: -20px;
    width: 100%;
  }

  .interact-content {
    height: 40px;
    line-height: 40px;
    position: relative;

    .panel-title-hr {
      background-color: #e9e9e9;
      height: 1px;
      left: -16px;
      position: absolute;
      right: -20px;
    }

    .setting-text {
      font-weight: bolder;
      margin-right: 62px;
    }
  }
}
</style>
<style lang="less">
.sub-chart-cat-icon {
  cursor: pointer;
  display: inline-block;
  font-size: 16px;
  margin-right: 8px;
  padding: 0 4px;

  &.active,
  &:hover {
    background-color: #eaeafd;
  }

  &.active {
    color: #6973ff;
  }
}
</style>
